/*
 *	Generate the syscall functions
 */

#include "syscall_name.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static char namebuf[128];

static void write_call(int n) {
  FILE *fp;
  int saves = 0;
  snprintf(namebuf, 128, "fuzixesp8266/syscall_%s.S", syscall_name[n]);
  fp = fopen(namebuf, "w");
  if (fp == NULL) {
    perror(namebuf);
    exit(1);
  }

  fprintf(fp,
          "\t.text\n\n"
          "\t.align 4\n\n"
          "\t.globl %1$s\n\n"
          "%1$s:\n",
          syscall_name[n]);

  switch (syscall_args[n]) {
  case VARARGS:
  case 4:
    fprintf(fp, "\tmov a6, a5\n");
  case 3:
    fprintf(fp, "\tmov a5, a4\n");
  case 2:
    fprintf(fp, "\tmov a4, a3\n");
  case 1:
    fprintf(fp, "\tmov a3, a2\n");
  case 0:
    break;
  }

  fprintf(fp, "\tmovi a2, %d\n", n);
  fprintf(fp, "\tsyscall\n");

  fprintf(fp, "\tbeqz a3, _no_error\n");
  fprintf(fp, "\tmovi a4, errno\n");
  fprintf(fp, "\ts32i a3, a4, 0\n");
  fprintf(fp, "_no_error:\n");
  fprintf(fp, "\tret\n");

  fclose(fp);
}

static void write_call_table(void) {
  int i;
  for (i = 0; i < NR_SYSCALL; i++)
    write_call(i);
}

static void write_makefile(void) {
  int i;
  FILE *fp = fopen("fuzixesp8266/Makefile", "w");
  if (fp == NULL) {
    perror("writing Makefile");
    exit(1);
  }
  fprintf(fp, "# Autogenerated by tools/syscall_esp8266\n");
  fprintf(fp, "CROSS_AS=xtensa-lx106-elf-as\nCROSS_AR=xtensa-lx106-elf-ar\n");
  fprintf(fp, "ASOPTS=\n\n");
  fprintf(fp, "ASRCS = syscall_%s.S\n", syscall_name[0]);
  for (i = 1; i < NR_SYSCALL; i++)
    fprintf(fp, "ASRCS += syscall_%s.S\n", syscall_name[i]);
  fprintf(fp, "\n\nASRCALL = $(ASRCS) $(ASYS)\n");
  fprintf(fp, "\nAOBJS = $(ASRCALL:.S=.o)\n\n");
  fprintf(fp, "syslib.lib: $(AOBJS)\n");
  fprintf(fp, "\techo $(AOBJS) >syslib.l\n");
  fprintf(fp, "\t$(CROSS_AR) rc syslib.lib $(AOBJS)\n\n");
  fprintf(fp, "$(AOBJS): %%.o: %%.S\n");
  fprintf(fp, "\t$(CROSS_AS) $(ASOPTS) -c -o $@ $<\n\n");
  fprintf(fp, "clean:\n");
  fprintf(fp, "\trm -f $(AOBJS) $(ASRCS) syslib.lib syslib.l *~\n\n");
  fclose(fp);
}

int main(int argc, char *argv[]) {
  write_makefile();
  write_call_table();
  exit(0);
}
